<script setup lang="ts">
import { nextTick, ref, watch } from 'vue';
import {
  type Connection,
  ConnectionMode,
  type Edge,
  Handle,
  type Node,
  Position,
  VueFlow,
  useVueFlow
} from '@vue-flow/core';
import { Background } from '@vue-flow/background';
import { MiniMap } from '@vue-flow/minimap';
import { Controls } from '@vue-flow/controls';
import '@vue-flow/core/dist/style.css';
import '@vue-flow/core/dist/theme-default.css';
import '@vue-flow/controls/dist/style.css';
import '@vue-flow/minimap/dist/style.css';
import {
  ApiOutlined,
  BranchesOutlined,
  CodeOutlined,
  DatabaseOutlined,
  PlayCircleOutlined,
  ReloadOutlined,
  SplitCellsOutlined,
  StopOutlined,
  SwapOutlined
} from '@ant-design/icons-vue';

// 定义props
interface Props {
  flowSteps: any[];
  selectedStepIndex?: number;
  connections?: any[];
  nodePositions?: Record<string, { x: number; y: number }>;
  autoConnect?: boolean;
}

const props = withDefaults(defineProps<Props>(), {
  selectedStepIndex: -1,
  connections: () => [],
  nodePositions: () => ({}),
  autoConnect: true
});

// 定义emits
const emit = defineEmits<{
  'update:flowSteps': [steps: any[]];
  'update:connections': [connections: any[]];
  'update:node-positions': [positions: Record<string, { x: number; y: number }>];
  'step-click': [step: any, index: number];
  'step-delete': [index: number];
  'step-edit': [step: any, index: number];
  'step-add': [stepType: string, position?: { x: number; y: number }];
}>();

// Vue Flow hooks
const { onConnect, onNodesChange, onEdgesChange } = useVueFlow();

// 响应式数据
const nodes = ref<Node[]>([]);
const edges = ref<Edge[]>([]);
const customEdges = ref<Edge[]>([]); // 用户自定义的边

// 步骤类型图标映射
const stepTypeIcons: Record<string, any> = {
  groovy: CodeOutlined,
  mapping: SwapOutlined,
  rest: ApiOutlined,
  sql: DatabaseOutlined,
  service: ApiOutlined,
  model: PlayCircleOutlined,
  condition: BranchesOutlined,
  parallel: SplitCellsOutlined,
  loop: ReloadOutlined,
  input_param: PlayCircleOutlined,
  output_param: StopOutlined
};

// 步骤类型标签映射
const stepTypeLabels: Record<string, string> = {
  groovy: 'Groovy脚本',
  mapping: '数据映射',
  rest: 'REST调用',
  sql: 'SQL查询',
  service: 'Service调用',
  model: '模型调用',
  condition: '条件分支',
  parallel: '并行执行',
  loop: '循环',
  input_param: '输入参数',
  output_param: '输出参数'
};

// 步骤类型颜色映射
const stepTypeColors: Record<string, string> = {
  groovy: '#52c41a',
  mapping: '#1890ff',
  rest: '#fa8c16',
  sql: '#722ed1',
  service: '#fa541c',
  model: '#eb2f96',
  condition: '#13c2c2',
  parallel: '#f5222d',
  loop: '#faad14',
  input_param: '#52c41a',
  output_param: '#f5222d'
};

// 将流程步骤转换为节点和边
function convertStepsToNodesAndEdges() {
  const newNodes: Node[] = [];
  const newEdges: Edge[] = [];

  let yPosition = 100;
  const xPosition = 300;
  const nodeSpacing = 150;

  // 添加开始节点
  const startPosition = props.nodePositions.start || { x: xPosition, y: 50 };
  newNodes.push({
    id: 'start',
    type: 'default',
    position: startPosition,
    data: {
      label: '开始',
      type: 'start'
    },
    style: {
      // background: '#f0f0f0',
      border: '2px solid #d9d9d9',
      borderRadius: '50%',
      width: '80px',
      height: '80px',
      display: 'flex',
      alignItems: 'center',
      justifyContent: 'center',
      fontSize: '14px',
      fontWeight: 'bold'
    }
  });

  // 处理每个步骤
  props.flowSteps.forEach((step, index) => {
    const nodeId = `step-${index}`;
    const isSelected = props.selectedStepIndex === index;

    // 获取保存的位置或使用默认位置
    const savedPosition = props.nodePositions[nodeId];
    const position = savedPosition || { x: xPosition, y: yPosition };

    // 创建主节点
    newNodes.push({
      id: nodeId,
      type: 'default',
      position,
      data: {
        id: nodeId,
        label: step.name,
        type: step.type,
        step,
        index
      },
      style: {
        background: isSelected ? '#e6f7ff' : '#fff',
        border: `2px solid ${isSelected ? '#1890ff' : stepTypeColors[step.type] || '#d9d9d9'}`,
        borderRadius: '8px',
        width: '200px',
        minHeight: '80px',
        padding: '12px',
        boxShadow: isSelected ? '0 4px 12px rgba(24, 144, 255, 0.3)' : '0 2px 8px rgba(0, 0, 0, 0.1)'
      }
    });

    // 连接到前一个节点（仅在autoConnect为true时）
    if (props.autoConnect && index === 0) {
      // 第一个步骤：连接开始节点
      newEdges.push({
        id: `start-to-${nodeId}`,
        source: 'start',
        target: nodeId,
        style: { stroke: '#d9d9d9' },
        deletable: true
      });
    } else if (props.autoConnect && index > 0) {
      const prevStep = props.flowSteps[index - 1];
      const prevNodeId = `step-${index - 1}`;

      // 根据前一个步骤的类型决定连接方式
      if (prevStep.type === 'condition') {
        // 条件分支：需要指定连接到哪个Handle
        // 这里简化处理，实际应该根据业务逻辑决定连接到true还是false分支
        newEdges.push({
          id: `${prevNodeId}-true-to-${nodeId}`,
          source: prevNodeId,
          sourceHandle: 'true',
          target: nodeId,
          label: '是',
          style: { stroke: '#52c41a' },
          labelStyle: { fill: '#52c41a', fontWeight: 'bold' },
          deletable: true
        });

        // 如果有下一个步骤，也连接false分支
        if (index < props.flowSteps.length - 1) {
          const nextNodeId = `step-${index + 1}`;
          newEdges.push({
            id: `${prevNodeId}-false-to-${nextNodeId}`,
            source: prevNodeId,
            sourceHandle: 'false',
            target: nextNodeId,
            label: '否',
            style: { stroke: '#fa8c16' },
            labelStyle: { fill: '#fa8c16', fontWeight: 'bold' },
            deletable: true
          });
        }
      } else if (prevStep.type === 'parallel' && prevStep.parallelConfig) {
        // 并行执行：从第一个分支连接
        newEdges.push({
          id: `${prevNodeId}-to-${nodeId}`,
          source: prevNodeId,
          sourceHandle: 'branch-0',
          target: nodeId,
          style: { stroke: '#1890ff' },
          deletable: true
        });
      } else if (prevStep.type === 'loop') {
        // 循环：从continue连接
        newEdges.push({
          id: `${prevNodeId}-to-${nodeId}`,
          source: prevNodeId,
          sourceHandle: 'continue',
          target: nodeId,
          style: { stroke: '#faad14' },
          deletable: true
        });
      } else {
        // 普通步骤：直接连接
        newEdges.push({
          id: `${prevNodeId}-to-${nodeId}`,
          source: prevNodeId,
          target: nodeId,
          style: { stroke: '#d9d9d9' },
          deletable: true
        });
      }
    }

    // 处理分支步骤的特殊连接
    if (step.type === 'condition' && step.conditionConfig) {
      // 条件分支：不需要创建额外的分支节点，Handle已经在节点模板中定义
      yPosition += nodeSpacing;
    } else if (step.type === 'parallel' && step.parallelConfig) {
      // 并行执行：不需要创建额外的分支节点，Handle已经在节点模板中定义
      yPosition += nodeSpacing;
    } else if (step.type === 'loop' && step.loopConfig) {
      // 循环：不需要创建额外的循环体节点，Handle已经在节点模板中定义
      // 添加循环回连接（从左侧Handle回到自身）
      newEdges.push({
        id: `${nodeId}-loop-back`,
        source: nodeId,
        sourceHandle: 'loop-back',
        target: nodeId,
        style: { stroke: '#722ed1', strokeDasharray: '5,5' },
        label: '循环',
        deletable: true
      });

      yPosition += nodeSpacing;
    } else {
      // 普通步骤：已在上面处理连接
      yPosition += nodeSpacing;
    }
  });

  // 添加结束节点
  if (props.flowSteps.length > 0) {
    const endPosition = props.nodePositions.end || { x: xPosition, y: yPosition };
    newNodes.push({
      id: 'end',
      type: 'default',
      position: endPosition,
      data: {
        label: '结束',
        type: 'end'
      },
      style: {
        // background: '#f0f0f0',
        border: '2px solid #d9d9d9',
        borderRadius: '50%',
        width: '80px',
        height: '80px',
        display: 'flex',
        alignItems: 'center',
        justifyContent: 'center',
        fontSize: '14px',
        fontWeight: 'bold'
      }
    });

    // 连接最后一个步骤到结束节点（仅在autoConnect为true时）
    if (props.autoConnect) {
      const lastStep = props.flowSteps[props.flowSteps.length - 1];
      const lastStepId = `step-${props.flowSteps.length - 1}`;

      if (lastStep.type === 'condition') {
        // 条件分支：两个分支都连接到结束节点
        newEdges.push({
          id: `${lastStepId}-true-to-end`,
          source: lastStepId,
          sourceHandle: 'true',
          target: 'end',
          style: { stroke: '#52c41a' },
          deletable: true
        });
        newEdges.push({
          id: `${lastStepId}-false-to-end`,
          source: lastStepId,
          sourceHandle: 'false',
          target: 'end',
          style: { stroke: '#fa8c16' },
          deletable: true
        });
      } else if (lastStep.type === 'parallel' && lastStep.parallelConfig) {
        // 并行执行：第一个分支连接到结束节点
        newEdges.push({
          id: `${lastStepId}-to-end`,
          source: lastStepId,
          sourceHandle: 'branch-0',
          target: 'end',
          style: { stroke: '#1890ff' },
          deletable: true
        });
      } else if (lastStep.type === 'loop') {
        // 循环：continue分支连接到结束节点
        newEdges.push({
          id: `${lastStepId}-to-end`,
          source: lastStepId,
          sourceHandle: 'continue',
          target: 'end',
          style: { stroke: '#faad14' },
          deletable: true
        });
      } else {
        // 普通步骤：直接连接
        newEdges.push({
          id: `${lastStepId}-to-end`,
          source: lastStepId,
          target: 'end',
          style: { stroke: '#d9d9d9' },
          deletable: true
        });
      }
    }
  }

  nodes.value = newNodes;

  // 加载保存的连线信息
  if (props.connections && props.connections.length > 0) {
    const nodeIds = new Set(newNodes.map(node => node.id));
    // 过滤出有效的保存连线（连接的节点存在）
    const validSavedConnections = props.connections.filter(
      edge => nodeIds.has(edge.source) && nodeIds.has(edge.target)
    );
    customEdges.value = validSavedConnections;
  } else {
    // 清理无效的自定义边（连接的节点不存在）
    const nodeIds = new Set(newNodes.map(node => node.id));
    customEdges.value = customEdges.value.filter(edge => nodeIds.has(edge.source) && nodeIds.has(edge.target));
  }

  // 合并自动生成的边和用户自定义的边
  edges.value = [...newEdges, ...customEdges.value];
}

// 监听步骤变化
watch(
  () => [props.flowSteps, props.selectedStepIndex, props.connections, props.nodePositions],
  () => {
    nextTick(() => {
      convertStepsToNodesAndEdges();
    });
  },
  { immediate: true, deep: true }
);

// 节点点击事件
function onNodeClick(event: any) {
  const node = event.node;
  if (node.data.type !== 'start' && node.data.type !== 'end' && node.data.type !== 'branch') {
    emit('step-click', node.data.step, node.data.index);
  }
}

// 边点击事件
function onEdgeClick(event: any) {
  console.log('Edge clicked:', event);
  // 可以在这里添加边点击的处理逻辑
}

// 连接事件
onConnect((connection: Connection) => {
  // 处理用户手动连接节点的逻辑
  // console.log('Connection created:', connection);

  // 创建新的边
  const newEdge: Edge = {
    id: `custom-${connection.source}-${connection.target}-${Date.now()}`,
    source: connection.source,
    target: connection.target,
    sourceHandle: connection.sourceHandle,
    targetHandle: connection.targetHandle,
    style: { stroke: '#1890ff', strokeWidth: 2 },
    type: 'default',
    deletable: true,
    data: { isCustom: true } // 标记为用户自定义边
  };

  // 添加到自定义边列表
  customEdges.value.push(newEdge);
  // 添加到边列表
  edges.value.push(newEdge);

  // 通知父组件流程图有修改
  syncFlowChangesToSteps();
});

// 节点变化事件
onNodesChange(changes => {
  // 处理节点位置变化等
  // console.log('Nodes changed:', changes);
  let positionChanged = false;

  // 应用节点变化
  changes.forEach(change => {
    if (change.type === 'position' && change.position) {
      const nodeIndex = nodes.value.findIndex(n => n.id === change.id);
      if (nodeIndex !== -1) {
        nodes.value[nodeIndex].position = change.position;
        positionChanged = true;
      }
    }
  });

  // 如果有位置变化，通知父组件保存位置信息
  if (positionChanged) {
    const positions: Record<string, { x: number; y: number }> = {};
    nodes.value.forEach(node => {
      if (node.id.startsWith('step-') || node.id === 'start' || node.id === 'end') {
        positions[node.id] = node.position;
      }
    });
    emit('update:node-positions', positions);
  }
});

// 边变化事件
onEdgesChange(changes => {
  // 处理边的变化（包括删除）
  // console.log('Edges changed:', changes);
  let hasChanges = false;

  changes.forEach(change => {
    if (change.type === 'remove') {
      // console.log('Removing edge:', change.id);
      // 删除边
      const edgeIndex = edges.value.findIndex(e => e.id === change.id);
      if (edgeIndex !== -1) {
        const removedEdge = edges.value[edgeIndex];
        edges.value.splice(edgeIndex, 1);
        hasChanges = true;

        // 如果是自定义边，也从自定义边列表中删除
        if (removedEdge.data?.isCustom) {
          const customIndex = customEdges.value.findIndex(e => e.id === change.id);
          if (customIndex !== -1) {
            customEdges.value.splice(customIndex, 1);
          }
        }
        console.log('Edge removed successfully:', change.id);
      }
    } else if (change.type === 'add' && change.item) {
      // 添加边
      edges.value.push(change.item);
      hasChanges = true;
    } else if (change.type === 'select') {
      // 选择变化，不需要同步到父组件
      // 跳过这些变化类型
    }
  });

  // 只有在真正有边的增删时才通知父组件
  if (hasChanges) {
    // 通知父组件流程图有修改
    syncFlowChangesToSteps();
  }
});

// 拖拽功能
const isDragOver = ref(false);

// 拖拽进入
function onDragOver(event: DragEvent) {
  event.preventDefault();
  if (event.dataTransfer) {
    event.dataTransfer.dropEffect = 'copy';
  }
  isDragOver.value = true;
}

// 拖拽离开
function onDragLeave(event: DragEvent) {
  event.preventDefault();
  isDragOver.value = false;
}

// 拖拽放置
function onDrop(event: DragEvent) {
  event.preventDefault();
  isDragOver.value = false;

  const stepType = event.dataTransfer?.getData('text/plain');
  if (stepType) {
    // 获取放置位置（相对于流程图容器）
    const rect = (event.currentTarget as HTMLElement).getBoundingClientRect();
    const position = {
      x: event.clientX - rect.left,
      y: event.clientY - rect.top
    };

    // 发射添加步骤事件
    emit('step-add', stepType, position);
  }
}

// 删除节点功能
function deleteNode(nodeId: string) {
  // 参数验证
  if (!nodeId || typeof nodeId !== 'string') {
    console.warn('deleteNode: nodeId is invalid', nodeId);
    return;
  }

  // 找到对应的步骤索引
  const stepIndex = Number.parseInt(nodeId.replace('step-', ''), 10);
  if (!Number.isNaN(stepIndex)) {
    emit('step-delete', stepIndex);
  }
}

// 同步流程图修改到flowSteps
function syncFlowChangesToSteps() {
  // 当流程图发生修改时，触发更新事件通知父组件保存
  // 这里不直接修改flowSteps，而是通知父组件有修改需要保存
  emit('update:flowSteps', props.flowSteps);

  // 同时传递连线信息
  emit('update:connections', customEdges.value);
}
</script>

<template>
  <div
    class="flow-chart-container"
    :class="{ 'drag-over': isDragOver }"
    @dragover="onDragOver"
    @dragleave="onDragLeave"
    @drop="onDrop"
  >
    <!-- 拖拽提示 -->
    <div v-if="isDragOver" class="drag-hint">
      <div class="drag-hint-content">
        <span>释放以添加步骤到流程图</span>
      </div>
    </div>

    <VueFlow
      v-model:nodes="nodes"
      v-model:edges="edges"
      :connection-mode="ConnectionMode.Loose"
      :default-zoom="0.8"
      :min-zoom="0.1"
      :max-zoom="2"
      :edges-deletable="true"
      :nodes-deletable="false"
      :connect-on-click="false"
      :delete-key-code="['Delete', 'Backspace']"
      class="flow-chart"
      @node-click="onNodeClick"
      @edge-click="onEdgeClick"
    >
      <!-- 自定义节点模板 -->
      <template #node-default="{ data }">
        <div class="custom-node" :class="[`node-${data.type}`, { 'node-selected': data.index === selectedStepIndex }]">
          <!-- 输入连接点 -->
          <Handle
            v-if="data.type !== 'start'"
            type="target"
            :position="Position.Top"
            class="node-handle node-handle-input"
          />

          <!-- 步骤节点 -->
          <div v-if="data.type !== 'start' && data.type !== 'end' && data.type !== 'branch'" class="step-node">
            <!-- 删除按钮 -->
            <button class="delete-btn" title="删除步骤" @click.stop="deleteNode(data.id)">×</button>

            <div class="step-header">
              <component :is="stepTypeIcons[data.type]" class="step-icon" />
              <span class="step-type-label">{{ stepTypeLabels[data.type] }}</span>
            </div>
            <div class="step-name">{{ data.label }}</div>
            <div v-if="data.step.description" class="step-description">{{ data.step.description }}</div>

            <!-- 不同步骤类型的特殊信息 -->
            <div v-if="data.type === 'groovy'" class="step-details">
              <div class="detail-item">脚本语言: Groovy</div>
              <div v-if="data.step.script" class="detail-item script-preview">
                {{ data.step.script.length > 30 ? data.step.script.substring(0, 30) + '...' : data.step.script }}
              </div>
            </div>
            <div v-else-if="data.type === 'mapping'" class="step-details">
              <div class="detail-item">数据映射配置</div>
              <div v-if="data.step.mappingConfig" class="detail-item config-preview">
                配置长度: {{ data.step.mappingConfig.length }} 字符
              </div>
            </div>
            <div v-else-if="data.type === 'rest'" class="step-details">
              <div class="detail-item method-url">
                <span class="method-badge" :class="data.step.method?.toLowerCase()">
                  {{ data.step.method || 'GET' }}
                </span>
                <span class="url-text">{{ data.step.url || '未配置URL' }}</span>
              </div>
            </div>
            <div v-else-if="data.type === 'sql'" class="step-details">
              <div class="detail-item">数据源: {{ data.step.dataSource || '默认' }}</div>
              <div v-if="data.step.query" class="detail-item query-preview">
                {{ data.step.query.length > 40 ? data.step.query.substring(0, 40) + '...' : data.step.query }}
              </div>
            </div>
            <div v-else-if="data.type === 'model'" class="step-details">
              <div class="detail-item">模型: {{ data.step.modelId || '未选择' }}</div>
              <div v-if="data.step.parameters" class="detail-item">
                参数配置: {{ data.step.parameters.length }} 字符
              </div>
            </div>
            <div v-else-if="data.type === 'condition' && data.step.conditionConfig" class="step-details">
              <div class="detail-item condition-expr">{{ data.step.conditionConfig.condition }}</div>
              <div class="detail-item branch-count">
                真分支: {{ data.step.conditionConfig.trueSteps?.length || 0 }} 步骤 假分支:
                {{ data.step.conditionConfig.falseSteps?.length || 0 }} 步骤
              </div>
            </div>
            <div v-else-if="data.type === 'parallel' && data.step.parallelConfig" class="step-details">
              <div class="detail-item">并发数: {{ data.step.parallelConfig.maxConcurrency }}</div>
              <div class="detail-item">分支数: {{ data.step.parallelConfig.branches?.length || 0 }}</div>
            </div>
            <div v-else-if="data.type === 'loop' && data.step.loopConfig" class="step-details">
              <div class="detail-item">条件: {{ data.step.loopConfig.condition }}</div>
              <div class="detail-item">最大迭代: {{ data.step.loopConfig.maxIterations }}</div>
              <div class="detail-item">循环步骤: {{ data.step.loopConfig.steps?.length || 0 }} 个</div>
            </div>
            <div v-else-if="data.type === 'input_param'" class="step-details">
              <div class="detail-item">输入参数定义</div>
              <div v-if="data.step.inputSchema" class="detail-item">
                Schema长度: {{ data.step.inputSchema.length }} 字符
              </div>
            </div>
            <div v-else-if="data.type === 'output_param'" class="step-details">
              <div class="detail-item">输出参数定义</div>
              <div v-if="data.step.outputSchema" class="detail-item">
                Schema长度: {{ data.step.outputSchema.length }} 字符
              </div>
            </div>
          </div>

          <!-- 开始/结束节点 -->
          <div v-else-if="data.type === 'start' || data.type === 'end'" class="control-node">
            {{ data.label }}
          </div>

          <!-- 分支节点 -->
          <div v-else class="branch-node">
            {{ data.label }}
          </div>

          <!-- 输出连接点 -->
          <!-- 条件分支：两个输出点 -->
          <template v-if="data.type === 'condition'">
            <Handle
              id="true"
              type="source"
              :position="Position.Bottom"
              class="node-handle node-handle-output node-handle-true"
              :style="{ left: '25%' }"
            />
            <Handle
              id="false"
              type="source"
              :position="Position.Bottom"
              class="node-handle node-handle-output node-handle-false"
              :style="{ left: '75%' }"
            />
          </template>

          <!-- 并行执行：多个输出点 -->
          <template v-else-if="data.type === 'parallel' && data.step.parallelConfig">
            <Handle
              v-for="(_, index) in data.step.parallelConfig.branches || []"
              :id="`branch-${index}`"
              :key="index"
              type="source"
              :position="Position.Bottom"
              class="node-handle node-handle-output node-handle-parallel"
              :style="{ left: `${((index + 1) * 100) / (data.step.parallelConfig.branches.length + 1)}%` }"
            />
          </template>

          <!-- 循环：一个输出点和一个回环点 -->
          <template v-else-if="data.type === 'loop'">
            <Handle
              id="continue"
              type="source"
              :position="Position.Bottom"
              class="node-handle node-handle-output node-handle-loop"
            />
            <Handle
              id="loop-back"
              type="source"
              :position="Position.Left"
              class="node-handle node-handle-output node-handle-loop-back"
            />
          </template>

          <!-- 普通步骤：单个输出点 -->
          <Handle
            v-else-if="data.type !== 'end' && data.type !== 'branch'"
            type="source"
            :position="Position.Bottom"
            class="node-handle node-handle-output"
          />
        </div>
      </template>

      <!-- 背景 -->
      <Background pattern-color="#f0f0f0" :gap="20" />

      <!-- 小地图 -->
      <MiniMap :node-color="node => stepTypeColors[node.data.type] || '#d9d9d9'" />

      <!-- 控制面板 -->
      <Controls />
    </VueFlow>
  </div>
</template>

<style scoped>
.flow-chart-container {
  width: 100%;
  height: 100%;
  position: relative;
}

.flow-chart {
  width: 100%;
  height: 100%;
  /* background: #fafafa; */
}

.custom-node {
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
}

.step-node {
  padding: 12px;
  background: #ffffffcc;
  border-radius: 8px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
  min-width: 180px;
  cursor: pointer;
  transition: all 0.3s ease;
}

.step-node:hover {
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.15);
  transform: translateY(-2px);
}

.node-selected .step-node {
  border: 2px solid #1890ff;
  box-shadow: 0 4px 12px rgba(24, 144, 255, 0.3);
}

.step-header {
  display: flex;
  align-items: center;
  margin-bottom: 8px;
}

.step-icon {
  margin-right: 6px;
  font-size: 16px;
}

.step-type-label {
  font-size: 12px;
  color: #666;
  font-weight: 500;
}

.step-name {
  font-size: 14px;
  font-weight: 600;
  color: #333;
  margin-bottom: 4px;
  word-break: break-word;
}

.step-description {
  font-size: 12px;
  color: #999;
  margin-bottom: 8px;
  word-break: break-word;
}

.branch-info {
  font-size: 11px;
  color: #666;
  background: #f5f5f5;
  padding: 4px 8px;
  border-radius: 4px;
  margin-top: 8px;
}

.condition-expr {
  font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
}

/* 步骤详情样式 */
.step-details {
  margin-top: 8px;
  font-size: 11px;
}

.detail-item {
  margin-bottom: 4px;
  color: #666;
  line-height: 1.4;
}

.detail-item:last-child {
  margin-bottom: 0;
}

/* 方法和URL显示 */
.method-url {
  display: flex;
  align-items: center;
  gap: 6px;
  flex-wrap: wrap;
}

.method-badge {
  display: inline-block;
  padding: 2px 6px;
  border-radius: 3px;
  font-size: 10px;
  font-weight: bold;
  color: white;
  text-transform: uppercase;
}

.method-badge.get {
  background: #52c41a;
}

.method-badge.post {
  background: #1890ff;
}

.method-badge.put {
  background: #fa8c16;
}

.method-badge.delete {
  background: #ff4d4f;
}

.url-text {
  font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
  font-size: 10px;
  color: #333;
  word-break: break-all;
}

/* 脚本和查询预览 */
.script-preview,
.query-preview {
  font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
  /* background: #f8f8f8; */
  padding: 4px 6px;
  border-radius: 3px;
  border-left: 3px solid #1890ff;
  font-size: 10px;
  color: #333;
  word-break: break-all;
}

.config-preview {
  /* background: #f0f9ff; */
  padding: 2px 6px;
  border-radius: 3px;
  color: #0066cc;
}

/* 条件表达式样式 */
.condition-expr {
  font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
  /* background: #fff7e6; */
  padding: 4px 6px;
  border-radius: 3px;
  border-left: 3px solid #fa8c16;
  color: #d46b08;
}

/* 分支计数样式 */
.branch-count {
  display: flex;
  gap: 8px;
  font-size: 10px;
  color: #666;
}

.control-node {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 80px;
  height: 80px;
  border-radius: 50%;
  /* background: #f0f0f0; */
  border: 2px solid #d9d9d9;
  font-size: 14px;
  font-weight: bold;
  color: #666;
}

.branch-node {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 120px;
  height: 60px;
  border-radius: 8px;
  font-size: 12px;
  font-weight: 500;
  color: #333;
}

/* Vue Flow 样式覆盖 */
:deep(.vue-flow__node) {
  border: none !important;
  background: transparent !important;
  padding: 0 !important;
}

:deep(.vue-flow__edge) {
  stroke-width: 2px;
}

:deep(.vue-flow__edge.selected) {
  stroke-width: 3px;
}

:deep(.vue-flow__controls) {
  bottom: 20px;
  left: 20px;
}

:deep(.vue-flow__minimap) {
  bottom: 20px;
  right: 20px;
  width: 200px;
  height: 150px;
  border: 1px solid #d9d9d9;
  border-radius: 8px;
}

/* :deep(.vue-flow__background) {
  background-color: #fafafa;
} */

/* Handle 连接点样式 */
.node-handle {
  width: 12px;
  height: 12px;
  border: 2px solid #fff;
  border-radius: 50%;
  background: #1890ff;
  transition: all 0.2s ease;
}

.node-handle:hover {
  width: 16px;
  height: 16px;
  border-width: 3px;
}

.node-handle-input {
  background: #52c41a;
}

.node-handle-output {
  background: #1890ff;
}

.node-handle-true {
  background: #52c41a;
}

.node-handle-false {
  background: #fa8c16;
}

.node-handle-parallel {
  background: #1890ff;
}

.node-handle-loop {
  background: #faad14;
}

.node-handle-loop-back {
  background: #722ed1;
}

/* Vue Flow Handle 样式覆盖 */
:deep(.vue-flow__handle) {
  width: 12px;
  height: 12px;
  border: 2px solid #fff;
  border-radius: 50%;
  transition: all 0.2s ease;
}

:deep(.vue-flow__handle:hover) {
  width: 16px;
  height: 16px;
  border-width: 3px;
}

:deep(.vue-flow__handle-top) {
  top: -6px;
}

:deep(.vue-flow__handle-bottom) {
  bottom: -6px;
}

:deep(.vue-flow__handle-left) {
  left: -6px;
}

:deep(.vue-flow__handle-right) {
  right: -6px;
}

/* 边的样式 */
:deep(.vue-flow__edge) {
  cursor: pointer;
}

:deep(.vue-flow__edge:hover) {
  stroke-width: 3px !important;
}

:deep(.vue-flow__edge.selected) {
  stroke-width: 3px !important;
  stroke-dasharray: 5, 5;
  animation: dash 1s linear infinite;
}

@keyframes dash {
  to {
    stroke-dashoffset: -10;
  }
}

/* 边的删除按钮 */
:deep(.vue-flow__edge-remove) {
  fill: #ff4d4f;
  /* background: #fff; */
  border-radius: 50%;
  width: 20px;
  height: 20px;
  border: 1px solid #ff4d4f;
}

/* 拖拽相关样式 */
.flow-chart-container {
  position: relative;
  width: 100%;
  height: 100%;
  transition: all 0.3s ease;
}

.flow-chart-container.drag-over {
  background-color: rgba(24, 144, 255, 0.1);
  border: 2px dashed #1890ff;
}

.drag-hint {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  background-color: rgba(24, 144, 255, 0.1);
  z-index: 1000;
  pointer-events: none;
}

.drag-hint-content {
  background: #1890ff;
  color: white;
  padding: 12px 24px;
  border-radius: 8px;
  font-size: 16px;
  font-weight: 500;
  box-shadow: 0 4px 12px rgba(24, 144, 255, 0.3);
}

/* 删除按钮样式 */
.delete-btn {
  position: absolute;
  top: -8px;
  right: -8px;
  width: 20px;
  height: 20px;
  border: none;
  border-radius: 50%;
  background: #ff4d4f;
  color: white;
  font-size: 14px;
  font-weight: bold;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 10;
  transition: all 0.2s ease;
  opacity: 0;
}

.step-node:hover .delete-btn {
  opacity: 1;
}

.delete-btn:hover {
  background: #ff7875;
  transform: scale(1.1);
}

:deep(.vue-flow__edge-remove:hover) {
  background: #ff4d4f;
  fill: #fff;
}
</style>
